let ylVue;

// 实现store 类
class Store {
  constructor(options) {
    this.$options = options;

    // 将 this 绑定到 store实例
    const store = this;
    const { commit, dispatch } = store;
    this.commit = function boundCommit(type, payload) {
      commit.call(store, type, payload);
    };
    this.dispatch = function boundDispatch(type, payload) {
      dispatch.call(store, type, payload);
    };

    // 遍历 getters所有的 key ,动态的赋值，值是函数的执行结果
    // 确保是 响应式的
    // 缓存一下
    this._wrappedGetters = options.getters;

    // 定义 computed
    const computed = {};
    this.getters = {};
    Object.keys(this._wrappedGetters).forEach((key) => {
      const fn = store._wrappedGetters[key];
      // computed 的函数没有参数 就做了一个高阶函数
      computed[key] = function () {
        return fn(store.state);
      };
      // 设置只读属性
      Object.defineProperty(store.getters, key, {
        get() {
          return store._vm[key];
        },
      });
    });

    // 构建响应式的数据
    this._vm = new ylVue({
      data: {
        $$state: options.state,
      },
      computed,
    });

    // 保存 mutations
    this._mutations = options.mutations || {};
    // 保存 actions
    this._actions = options.actions || {};
  }

  commit(type, payload) {
    // 根据type 获取 mutation
    let entry = this._mutations[type];
    if (!entry) {
      console.error('一个 未知的 mutation type');
      return;
    }
    entry(this.state, payload);
  }

  dispatch(type, payload) {
    // 根据type 获取 mutation
    let entry = this._actions[type];
    if (!entry) {
      console.error('一个 未知的 action type');
      return;
    }
    return entry(this, payload);
  }

  // 做成一个私有的  不让用户去覆盖
  get state() {
    return this._vm._data.$$state;
  }
  set state(v) {
    console.error('please use replaceState to reset state');
  }
}

// 实现 install 方法
function install(Vue) {
  ylVue = Vue;

  Vue.mixin({
    beforeCreate() {
      if (this.$options.store) {
        Vue.prototype.$store = this.$options.store;
      }
    },
  });
}

export default { Store, install };
